// websocket配置文件
export default class SocketService {
    // 单例设计模式
    static instance = null;
    static get Instance () {
      if (!this.instance) {
        this.instance = new SocketService()
      }
      return this.instance
    }
    // websocket对象
    ws = null;

    // 当前是否链接成功
    _connected = false;
    // 链接成功的函数
    connectQueue = []
    // 代理_connected
    get connected () {
      return this._connected
    }
    // 代理_connected，当设置_connected为true时，执行connectQueue里所有的函数。为了解决当ws还没有链接就发送数据了
    set connected(newV) {
      this._connected = newV
      if (newV && !!this.connectQueue.length) {
        this.connectQueue.forEach(cb => cb())
      } 
    }

    // 链接失败时，重复链接的次数
    retryConnectCount = 0;
    /** 
     * @brief        : 链接websocket
     * @return        {*}
     **/    
    connect() {
      if(!window.WebSocket) {
        return console.log('您的浏览器不支持WebSocket！');
      }
      this.ws = new WebSocket('ws://localhost:9999')
      // 当链接成功时
      this.ws.onopen = () => {
        console.log('WebSocket链接成功');
        this.retryConnectCount = 0;
        this.connected = true
      }
      // 1、当链接不上时
      // 2、当服务器发生异常时，都会调用该函数
      this.ws.onclose = () => {
        this.connected = false;
        console.log('WebSocket关闭链接');
        this.retryConnectCount++;
        // 当链接不上时，重试链接.并且随着重试的次数，重新链接的请求时间就越长
        setTimeout(() => {
          this.connect()
        }, 500 * this.retryConnectCount)
      }
      //  当收到信息
      this.ws.onmessage = (msg) => {
        console.log('websocket返回的数据', msg);
        // msg.data就是后端返回的数据
        if (typeof msg.data == 'string') {
          let res = JSON.parse(msg.data)
          console.log('解析的数据1', res);
          // 先判断有没有函数
          if (this.callBackMapping[res.socketType] || this.callBackMapping[res.socketType + res.chartName]) {
            if (res.action == 'getData') {
              this.callBackMapping[res.socketType](JSON.parse(res.data))
            } else if (res.action == 'themeChange') {
              this.callBackMapping[res.socketType]()
            } else if (res.action == 'changeMap') {
              this.callBackMapping[res.socketType](res.value)
            } else if (res.action == 'fullScreen') {
              console.log('fullScreen', res, this.callBackMapping);
              this.callBackMapping[res.socketType + res.chartName](res)
            }
          }
        } else if (msg.data instanceof Blob) {
            const reader = new FileReader();
            reader.readAsText(msg.data, "UTF-8");
            reader.onload = () => {
                //字符串和json格式
                let res = JSON.parse(reader.result);
                console.log('解析的数据2', res);
                // 先判断有没有函数
                if (this.callBackMapping[res.socketType + res.chartName]) {
                  if (res.action == 'fullScreen') {
                    console.log('fullScreen', res, this.callBackMapping);
                    this.callBackMapping[res.socketType + res.chartName](res)
                  }
                }
            }
        }

      }
    }
    // 业务类型和回调函数的关系
    callBackMapping = {} 
    /** 
     * @brief        : 往callbackmapping里添加函数
     * @param         {*} socketType: 业务类型 （trendData sellerData mapData rankData hotData stockData，fullScreen，themeChange）
     * @param         {*} callback: 对应的回调函数
     * @return        {*}
     **/    
    registerCallback(socketType, callback) {
      this.callBackMapping[socketType] = callback
    }
    /** 
     * @brief        : 往callbackmapping里删除函数
     * @param         {*} socketType:业务类型 （trendData sellerData mapData rankData hotData stockData，fullScreen，themeChange）
     * @return        {*}
     **/    
    unRegisterCallback(socketType) {
      this.callBackMapping[socketType] = null
    }

    /** 
     * @brief        : ws发送的数据
     * @param         {*} data: 数据
     * @return        {*}
     **/    
    send(data) {
      // 当链接成功时，直接发送数据
      if (this.connected) {
        console.log('发送数据给服务器:', JSON.stringify(data))
        this.ws.send(JSON.stringify(data))
      } else {  // 未连接成功时，将待执行数据放入队列
        this.connectQueue.push(() => {
          console.log('发送数据给服务器:', JSON.stringify(data))
          this.ws.send(JSON.stringify(data))
        })
      }
    }
}